#include <stdio.h>

#include <string.h>

#include <openssl/evp.h>

#include <openssl/x509.h>

#include <openssl/ssl.h>

#include <openssl/pem.h>

#include <openssl/err.h>

#include <sys/socket.h>

#include <unistd.h>

#include <netinet/in.h>?

#include <arpa/inet.h>

#include <iostream>

#define SERVER_IP "127.0.0.1"

#define SERVER_PORT 8443

int main(int argc, char* argv[]) {

	int ret;

	////////////

	// ��ʼ�� //

	////////////

	SSL_CTX* ctx;

	SSL_METHOD *meth;

	OpenSSL_add_ssl_algorithms();

	SSL_load_error_strings();

	//meth = (SSL_METHOD *)TLS_client_method();

	meth = (SSL_METHOD *)GMTLS_client_method();

	ctx = SSL_CTX_new(meth);

	if (!ctx) {

		ERR_print_errors_fp(stderr);

		std::cout << "SSL_CTX_new error." << std::endl;
		printf("SSL_CTX_new error.\n");

		return -1;

	}

	//SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384");

  //? SSL_CTX_set_max_proto_version(ctx,TLS1_2_VERSION);

  //? SSL_CTX_set_min_proto_version(ctx,TLS1_2_VERSION);

	///////////////////////

	// ����ԭʼ��TCP���� //

	///////////////////////

	int client_socket;

	struct sockaddr_in addr_server;

	client_socket = socket(AF_INET, SOCK_STREAM, 0);

	if (client_socket == -1) {

		//std::cout << "socket error." << std::endl;
		printf("socket error.");

		return -1;

	}

	memset(&addr_server, 0, sizeof(addr_server));

	addr_server.sin_family = AF_INET;

	addr_server.sin_addr.s_addr = inet_addr(SERVER_IP);

	addr_server.sin_port = htons(SERVER_PORT);

	ret = connect(client_socket, (struct sockaddr*) &addr_server, sizeof(addr_server));

	if (ret == -1) {

		std::cout << "connect error." << std::endl;
		printf("connect error.");

		return -1;

	}

	/////////////////////////////////////

	// TCP�����Ѿ�������ִ��Client SSL //

	/////////////////////////////////////

	SSL* ssl;

	X509* server_certificate;

	char* str;

	ssl = SSL_new(ctx);

	if (ssl == NULL) {

		std::cout << "SSL_new error." << std::endl;
		printf("SSL_new error.\n");

		return -1;

	}

	SSL_set_fd(ssl, client_socket);

	ret = SSL_connect(ssl);

	if (ret == -1) {

		//std::cout << "SSL_connect error." << std::endl;
		printf("SSL_connect error.");

		ERR_print_errors_fp(stderr);

		return -1;

	}

	ERR_print_errors_fp(stderr);

	// �������Ļ�ȡ����ͻ�ȡ��������֤��������ǿ�ѡ�ģ�����Ӱ�����ݽ���

	// ��ȡcipher

	std::cout << "SSL connection using: " << SSL_get_cipher(ssl) << std::endl;


	////////////////

	//? ���ݽ���? //

	////////////////

	char buf[4096];
       char code[8];
       printf("请输入股票代码：");
       scanf("%s",code);

	ret = SSL_write(ssl, code, strlen(code));

	if (ret == -1) {

		//std::cout << "SSL_write error." << std::endl;
		printf("SSL_write error.");

		return -1;

	}

	ret = SSL_read(ssl, buf, sizeof(buf) - 1);

	if (ret == -1) {

		//std::cout << "SSL_read error." << std::endl;
		printf("SSL_read error.");

		return -1;

	}

	buf[ret] = '\0';

	std::cout << buf << std::endl;
	printf("查询的股票信息：\n");
	printf("%s",&buf[ret]);

    ret = SSL_read(ssl, buf, sizeof(buf) - 1);


	if (ret == -1) {

		//std::cout << "SSL_read error." << std::endl;
		printf("SSL_read error.");

		return -1;

	}

	buf[ret] = '\0';
	std::cout << buf << std::endl;
	SSL_shutdown(ssl);/* send SSL/TLS close_notify */

	/////////////

	// Cleanup //

	/////////////

	close(client_socket);

	SSL_free(ssl);

	SSL_CTX_free(ctx);

	return 0;

}
